MDX Preview Setup Guide
This guide will help you set up a complete MDX editing workflow with syntax highlighting, live preview, and hot reload for Docusaurus running in Docker with Cloudflare Tunnel.
- How to enable MDX syntax highlighting in VS Code
- Setting up live preview without constant Docker restarts
- Configuring hot reload for instant changes
- Secure preview access via Cloudflare Tunnel
Understanding the Problem
When working with .mdx files in VS Code, you may encounter:
- ❌ No syntax highlighting (plain text appearance)
- ❌ No "Open Preview" option like
.mdfiles have - ❌ Manual Docker restarts needed to see changes
- ❌ No live reload during development
This guide solves all these issues.
Part 1: VS Code MDX Syntax Highlighting
Step 1: Install MDX Extension
- Open VS Code Extensions (
Ctrl+Shift+X) - Search for "MDX" (by unifiedjs is recommended)
- Click Install on SSH: [your-server] (if using Remote SSH)
- Reload VS Code:
Ctrl+Shift+P→ Developer: Reload Window
Step 2: Configure File Association
Open Settings (JSON) and add:
"files.associations": {
"*.mdx": "mdx"
}
Step 3: Verify Language Mode
- Open any
.mdxfile - Check bottom-right of VS Code status bar
- It should show MDX (not "Plain Text")
- If not, click it and select MDX
After setup, you should see colorful syntax highlighting for:
- Markdown headers, bold, italic
- JSX components like
<Tabs>,<Details> - Import statements
- Code blocks
Part 2: Live Preview Setup (No Restarts Needed)
Why Can't We Use "Open Preview"?
Unlike .md files, MDX contains React components that need a renderer. The best preview is the Docusaurus dev server itself.
Solution Architecture
Part 3: Docker Configuration for Hot Reload
Option A: Complete docker-compose.yml Setup
Create or update your docker-compose.yml:
services:
docusaurus:
image: node:20-alpine
container_name: docusaurus
working_dir: /site
restart: unless-stopped
volumes:
- /opt/docker-data/apps/docusaurus/site:/site
- docusaurus_node_modules:/site/node_modules
command: sh -c "npm run start -- --host 0.0.0.0 --port 3000"
environment:
# Enable file watching in Docker (critical for hot reload)
- CHOKIDAR_USEPOLLING=true
- WATCHPACK_POLLING=true
- CHOKIDAR_INTERVAL=1000
ports:
# Expose ONLY to localhost (safe for Cloudflare Tunnel)
- "127.0.0.1:3000:3000"
volumes:
docusaurus_node_modules:
Why This Configuration?
| Setting | Purpose |
|---|---|
--host 0.0.0.0 | Container listens on all interfaces (required in Docker) |
127.0.0.1:3000:3000 | Exposes port only to localhost (not public) |
CHOKIDAR_USEPOLLING | Enables file watching in Docker environment |
docusaurus_node_modules volume | Persists dependencies, avoids reinstalling on restart |
Part 4: Initial Setup & Testing
Step 1: Install Dependencies (One-Time)
# Start the container
docker compose up -d
# Install dependencies
docker compose exec docusaurus npm install
# Check logs
docker logs -f docusaurus
Step 2: Verify Dev Server
On your server, test that Docusaurus is running:
curl -I http://127.0.0.1:3000
Expected output:
HTTP/1.1 200 OK
Content-Type: text/html
You only need to do this ONCE. The container will keep running and auto-reload on file changes.
Part 5: Cloudflare Tunnel Configuration
Step 1: Configure Tunnel Ingress
Edit your Cloudflare Tunnel configuration:
ingress:
# Dev preview subdomain
- hostname: docs-dev.yourdomain.com
service: http://localhost:3000
# Other services...
# Catch-all
- service: http_status:404
Step 2: Restart Tunnel
cloudflared tunnel run <tunnel-name>
Step 3: Secure Your Preview (Important!)
Without protection, anyone can access your dev preview!
Option A: Cloudflare Access (Recommended)
- Go to Cloudflare Zero Trust dashboard
- Access → Applications → Add application
- Choose Self-hosted
- Domain:
docs-dev.yourdomain.com - Policy: Allow only your email
- Save and deploy
Option B: Alternative Authentication
If you don't use Cloudflare Access, consider:
- HTTP basic auth in Docusaurus config
- VPN-only access
- IP whitelist
Part 6: Your New Workflow (No Restarts!)
Daily Development Process
Step-by-Step
- Open
https://docs-dev.yourdomain.comin browser - Edit any
.mdxfile in VS Code - Save the file (
Ctrl+S) - Watch browser auto-refresh (2-5 seconds)
- ✅ No Docker restart needed!
Part 7: Troubleshooting
Issue 1: No Syntax Highlighting
Symptom: MDX files appear as plain text
Solutions:
# Check language mode (bottom-right of VS Code)
# Should show "MDX", not "Plain Text"
# If wrong, manually select MDX:
# Click language mode → Search "MDX" → Select
Issue 2: Hot Reload Not Working
Symptom: Changes don't appear after saving
Solutions:
Check container is running dev server:
docker logs docusaurus | grep "webpack compiled"
Verify environment variables:
docker compose exec docusaurus env | grep CHOKIDAR
Increase polling interval:
environment:
- CHOKIDAR_INTERVAL=2000 # Slower system? Use 2-3 seconds
Force restart (if needed):
docker compose restart docusaurus
Issue 3: Tunnel Can't Reach Dev Server
Symptom: docs-dev.yourdomain.com shows error
Solutions:
Check port binding:
docker port docusaurus
# Should show: 3000/tcp -> 127.0.0.1:3000
Test from server:
curl http://localhost:3000
# Should return HTML
Verify tunnel configuration:
cloudflared tunnel info <tunnel-name>
Issue 4: "Open Preview" Still Missing
Workaround (if you want simple markdown preview):
// settings.json
"files.associations": {
"*.mdx": "markdown"
}
⚠️ Limitation: JSX components won't render, but basic Markdown structure will preview.
Part 8: Advanced Tips
Tip 1: Multiple Preview URLs
You can have both dev and production:
ingress:
# Dev preview (live reload)
- hostname: docs-dev.yourdomain.com
service: http://localhost:3000
# Production build
- hostname: docs.yourdomain.com
service: http://localhost:3001
Tip 2: VS Code Port Forwarding Alternative
If you don't want Cloudflare Tunnel for dev:
- In VS Code (Remote SSH)
- Open Ports tab
- Click Forward a Port
- Enter
3000 - Click Open in Browser
✅ Stays private, no tunnel configuration needed!
Tip 3: Build Production to Test
Before deploying:
# Build production version
docker compose exec docusaurus npm run build
# Test production locally
docker compose exec docusaurus npm run serve -- --port 3001
Tip 4: Clear Cache on Weird Issues
# Clear Docusaurus cache
docker compose exec docusaurus npm run clear
# Or full restart
docker compose down
docker compose up -d
Part 9: Quick Reference
Common Commands
# Start Docusaurus dev server
docker compose up -d
# View live logs
docker logs -f docusaurus
# Install new package
docker compose exec docusaurus npm install <package-name>
# Restart container
docker compose restart docusaurus
# Stop container
docker compose down
# Full cleanup (removes node_modules volume)
docker compose down -v
File Locations
| Path | Description |
|---|---|
/opt/docker-data/apps/docusaurus/site/ | Your Docusaurus project |
/opt/docker-data/apps/docusaurus/site/docs/ | MDX documentation files |
/opt/docker-data/apps/docusaurus/site/docusaurus.config.js | Main config |
docker-compose.yml | Container configuration |
Port Reference
| Port | Purpose |
|---|---|
3000 | Dev server (hot reload) |
3001 | Production build (optional) |
Summary Checklist
Use this checklist to verify your setup:
- MDX extension installed in VS Code
- Syntax highlighting works (colors visible)
-
docker-compose.ymlconfigured with polling environment variables - Container running and accessible on
localhost:3000 - Cloudflare Tunnel pointing to
localhost:3000 - Cloudflare Access protecting dev preview
- File changes trigger hot reload (test by editing a file)
- Browser auto-refreshes on save
What You've Achieved
✅ Syntax Highlighting: MDX files are colorful and readable
✅ Live Preview: True Docusaurus rendering with all components
✅ Hot Reload: Changes appear automatically, no restarts
✅ Secure Access: Cloudflare Tunnel with authentication
✅ Developer Experience: Edit → Save → See results instantly
Now you can focus on writing great documentation without fighting your tools!
Additional Resources
Last Updated: February 2, 2026
Tested With: Docusaurus 3.x, Node 20, Docker Compose, Cloudflare Tunnel